#if !defined(glib_g2_io_h)
#define glib_g2_io_h

#include <iostream>
#include <xtd/bistream>
#include <xtd/bostream>

namespace g2 {

template <class T> class basic_vector;
template <class T> class basic_box;
template <class T> class basic_matrix;
template <class T> class basic_smatrix;
template <class T> class basic_translation;
template <class T> class basic_rotation;
template <class T> class basic_rigid;
template <class T> class basic_stretched_rotation;
template <class T> class basic_rigid_scale;
template <class T> class basic_affine;
template <class T> class basic_perspective;

template <class T>
inline std::ostream & operator << (std::ostream & s, const basic_vector<T> & v)
	{ return s << v.x << ' ' << v.y; }

template <class T>
inline std::istream & operator >> (std::istream & s, basic_vector<T> & v)
	{ return s >> v.x >> v.y; }

template <class T>
inline std::ostream & operator << (std::ostream & s, const basic_box<T> & b)
	{ return s << b.x1 << ' ' << b.y1 << ' ' << b.x2 << ' ' << b.y2; }

template <class T>
inline std::istream & operator >> (std::istream & s, basic_box<T> & b)
	{ return s >> b.x1 >> b.y1 >> b.x2 >> b.y2; }

template <class T>
inline std::ostream & operator << (std::ostream & s, const basic_smatrix<T> & m)
	{ return s << m.xx << ' ' << m.xy << ' ' << m.yy; }

template <class T>
inline std::istream & operator >> (std::istream & s, basic_smatrix<T> & m)
	{ return s >> m.xx >> m.xy >> m.yy; }

template <class T>
inline std::ostream & operator << (std::ostream & s, const basic_matrix<T> & m)
	{ return s << m.xx << ' ' << m.xy << ' ' << m.yx << ' ' << m.yy; }

template <class T>
inline std::istream & operator >> (std::istream & s, basic_matrix<T> & m)
	{ return s >> m.xx >> m.xy >> m.yx >> m.yy; }

template <class T>
inline std::ostream & operator << (std::ostream & s, const basic_translation<T> & t)
	{ return s << t.d; }

template <class T>
inline std::istream & operator >> (std::istream & s, basic_translation<T> & t)
	{ return s >> t.d; }

template <class T>
inline std::ostream & operator << (std::ostream & s, const basic_rotation<T> & t)
	{ return s << t.angle(); }

template <class T>
inline std::istream & operator >> (std::istream & s, basic_rotation<T> & t)
{
	T angle;
	s >> angle;
	t.angle(angle); 
	return s;
}

template <class T>
inline std::ostream & operator << (std::ostream & s, const basic_rigid<T> & t)
	{ return s << t.r << ' ' << t.d; }

template <class T>
inline std::istream & operator >> (std::istream & s, basic_rigid<T> & t)
	{ return s >> t.r >> t.d; }

template <class T>
inline std::ostream & operator << (std::ostream & s, const basic_stretched_rotation<T> & t)
	{ return s << t.p << ' ' << t.q; }

template <class T>
inline std::istream & operator >> (std::istream & s, basic_stretched_rotation<T> & t)
	{ return s >> t.p >> t.q; }

template <class T>
inline std::ostream & operator << (std::ostream & s, const basic_rigid_scale<T> & t)
	{ return s << t.r << ' ' << t.d; }

template <class T>
inline std::istream & operator >> (std::istream & s, basic_rigid_scale<T> & t)
	{ return s >> t.r >> t.d; }

template <class T>
inline std::ostream & operator << (std::ostream & s, const basic_affine<T> & t)
	{ return s << t.r << ' ' << t.d; }

template <class T>
inline std::istream & operator >> (std::istream & s, basic_affine<T> & t)
	{ return s >> t.r >> t.d; }

template <class T>
inline std::ostream & operator << (std::ostream & s, const basic_perspective<T> & t)
	{ return s << t.a << ' ' << t.b << ' ' << t.c; }

template <class T>
inline std::istream & operator >> (std::istream & s, basic_perspective<T> & t)
	{ return s >> t.a >> t.b >> t.c; }

//binary

template <class T>
inline xtd::bostream & operator << (xtd::bostream & s, const basic_vector<T> & v)
	{ return s.put(v); }

template <typename T>
inline xtd::bistream & operator >> (xtd::bistream & in, basic_vector<T> & v) 
	{ return in.get(v); }

template <class T>
inline xtd::bostream & operator << (xtd::bostream & s, const basic_box<T> & b)
	{ return s.put(b); }

template <class T>
inline xtd::bistream & operator >> (xtd::bistream & s, basic_box<T> & b)
	{ return s.get(b); }

template <class T>
inline xtd::bostream & operator << (xtd::bostream & s, const basic_smatrix<T> & m)
	{ return s.put(m); }

template <typename T>
inline xtd::bistream & operator >> (xtd::bistream & in, basic_smatrix<T> & m) {
	return in.get(m);
}

template <class T>
inline xtd::bostream & operator << (xtd::bostream & s, const basic_matrix<T> & m)
	{ return s.put(m); }

template <typename T>
inline xtd::bistream & operator >> (xtd::bistream & in, basic_matrix<T> & m) {
	return in.get(m);
}

} // g2

#endif // glib_g2_io_h